import os
import threading
import logging
import time

from . import utils
from . import input_dir, output_dir

LOG = logging.getLogger(__name__)


class Separate(threading.Thread):
    Instance = None

    def __new__(cls, *args, **kwargs):
        if cls.Instance and isinstance(cls.Instance, Separate) and cls.Instance.is_alive():
            raise Exception('task={} is separating'.format(getattr(cls.Instance, 'audio_filename')))
        cls.Instance = object.__new__(cls)
        return cls.Instance

    def __init__(self, audio_filename: str):
        super().__init__()
        self.audio_filename = audio_filename
        self.audio_filepath = os.path.join(input_dir, self.audio_filename)
        self.separate_command = os.path.join('scripts', 'separate.sh')
        self.success_flag = None
        self.used_time = None
        self.progress = None
        self.start_time = time.perf_counter()
        self.err_log = None

    @property
    def status(self):
        if self.success_flag is None:
            used_time = int(time.perf_counter() - self.start_time)
        else:
            used_time = self.used_time
        return {
            'task': self.audio_filename,
            'success_flag': self.success_flag,
            'used_time': used_time,
            'progress': self.progress,
            'err_log': self.err_log
        }

    def split_audio(self):
        free_mem = utils.get_gpu_free_mem()
        max_time = int(free_mem / 1000 * 40)
        utils.split_audio(self.audio_filepath, max_time, input_dir)

    def run(self):
        self.split_audio()
        split_audio_dir = os.path.join(input_dir, self.audio_filename.split('.')[0])
        separate_output_dir = os.path.join(output_dir, self.audio_filename.split('.')[0])
        split_audio_dir_files = list(os.listdir(split_audio_dir))
        for i, filename in enumerate(split_audio_dir_files):
            filepath = os.path.join(split_audio_dir, filename)
            cmd = 'sh {} {} {} {}'.format(self.separate_command, filepath, separate_output_dir, 600)
            LOG.info(cmd)
            try:
                self.progress = i / len(split_audio_dir_files) * 100
                utils.run_subprocess_check_output(cmd)
            except Exception as e:
                self.err_log = err_msg = 'separate failed, cmd={}, err={}'.format(cmd, str(e))
                LOG.error(err_msg)
            else:
                self.progress = (i + 1) / len(split_audio_dir_files) * 100
        else:
            self.success_flag = True
        self.used_time = int(time.perf_counter() - self.start_time)
        LOG.info('{} spleeter separate complete'.format(self.audio_filename))
